/******************************************************************************
*
* This file is part of FreeTrack (http://code.google.com/p/qtfreetrack).
* BY Willy Gardiol (willy@gardiol.org)
*
* FreeTrack is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeTrack is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/

#ifndef LAYERMAP_H
#define LAYERMAP_H

#include "IncFreeTrack.h"
#include "layer.h"

#define MAP_MAX_POINTS 4

class MapCacheManager;

class chunkKey
{
public:
    int x;
    int y;
    int zoom;

public:
    bool operator==(chunkKey key ) const;
};

uint qHash( const chunkKey& key );

struct mapChunk
{
    QImage image;
    QDateTime last_used;
    chunkKey key;
};

class LayerMap : public Layer
{
    Q_OBJECT

public: // Initialize, load and destruct
    explicit LayerMap(QString t, QString d);
    ~LayerMap();
    // Load a map
    bool loadMap( const QString& filename);

    bool loadOziMap( const QString& map_filename, QList<QPoint>& new_pointsXX, QList<QPointF>& new_pointsLL );
    bool loadCompeImp( const QString& imp_filename, QList<QPoint>& new_pointsXX, QList<QPointF>& new_pointsLL );
    bool loadCalibration( const QString& cal_filename, QList<QPoint>& new_pointsXX, QList<QPointF>& new_pointsLL, QString& t, QString& d );

public: // Map drawing functions
    // Draw the map with transformations calibration
    void paintLayer(QPainter&, const QTransform& , const QRectF&);
    // Get the cropped map
    void paintUncalibrated( QPainter&, QPoint, QRect );


public: // Access map data
    // Get map calibration points (x,y)
    void getPointsXY( QList<QPoint>& );
    // Get map calibration points (lat/lon)
    void getPointsLL( QList<QPointF>& );
    // Set all map points (centralized here for efficient save to disk)
    void setPoints( const QList<QPoint>&, const QList<QPointF>& );

    // Get image rect
    QRect getRect();

public: // Layer redefined mtethods
    // Return a widget used to configure the layer. The caller must display the widget.
    FreeTrackWidget* getConfigureLayer();
    // Return a widget used to display the map on the layer manager
    FreeTrackWidget* getLayerLabel();
    // Clear map cache
    void clearCache();
    // Rebuild the cache
    bool cacheRebuild();

private slots:
    void loadMissingChunks(); // QHash<int, QPoint>,int );

private: // calibration data and methods
    // X,Y points
    QList<QPoint> pointsXY;
    // Lat,Lon points
    QList<QPointF> pointsLL;

    // Store the transformation matrixes
    QTransform image_to_wgs84;
    QTransform wgs84_to_image;
    QTransform use_matrix;

    // Is map calibrated?
    bool calibrated;
    // Save calibration file
    void saveCalibration();
    // Calculate the matrixes
    void calibrateMatrix();

private: // Chunk cache and management
    // Number of chunks in image at zoom == ?
    QHash<int,int> chunks_cols;
    QHash<int,int> chunks_rows;

    // Chunks hash: keep all the chunks stored with their key
    QHash<chunkKey, mapChunk*> chunk_pool;

    // Build all the keys for the chunks to be draw
    QList<chunkKey> calculateChunkKeys( int,int, int, int, int );

    QList<chunkKey> MissingChunkKeys;

    mapChunk* allocateChunk();
    int allocated_chunks;

    int calcZoomFactor(qreal,qreal,qreal);

private: // map status and info
    // Is image loaded?
    bool loaded;
    // image filename
    QString img_filename;
    // Cache file name
    QString cache_basename;
    // Image area boundary rect
    QRect image_rect;
    // Store the maximum zoom factor
    int max_zoom_factor;
    // If we are ready to redraw or still loading chunks
    bool ready_for_draw;

};

#endif // LAYERMAP_H
